#include <pthread.h>
#include <rid.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <fn85.h>
#include <rid_fn85.h>

#include <nit/macros.h>
#include <nit/palloc.h>
#include <nit/list.h>
#include <nit/set.h>
#include <nit/map.h>

#include <oas.h>

#include "pum.h"
#include "global.h"
#include "care.h"

/* Rid none; */
Rid done = { 41, 86, 49, 74, 251, 224, 14, 16, 251, 224, 14, 16, 251, 224, 14,
	     16 };
Rid help = { 53, 106, 90, 1, 251, 224, 14, 16, 251, 224, 14, 16, 251, 224, 14,
	     16 };
/* Rid hurt; */
Rid how = { 53, 201, 87, 249, 251, 224, 14, 16, 251, 224, 14, 16, 251, 224,
	    14, 16} ;
/* Rid what = { 100, 49, 8, 8, 251, 224, 14, 16, 251, 224, 14, 16, 251, 224, 14, */
/* 	     16 }; */

/* Encourage what is good for focus and stop what is bad for focus,
   if what is good or bad is unknown or incosistant, try to figure it out.
*/

typedef struct {
	Rid focus;
	Nit_map known; /* good or bad */
} Care;

void
care_ask_help(Care *care, const Rid self, const Rid to, Oas_sys *sys)
{
	Pum_val *pum_help = global_get_pum(sys);
	Pum_val *pum_focus = global_get_pum(sys);
	Pum_val *pum_how = global_get_pum(sys);
	Pum_val *pum_done = global_get_pum(sys);

	pum_val_init(pum_help, PUM_WHAT, self, help, NULL);
	pum_val_init(pum_focus, PUM_TO, pum_help->id, care->focus, NULL);
	pum_val_init(pum_how, PUM_WHAT, pum_focus->id, how, NULL);
	pum_val_init(pum_done, PUM_WHAT, pum_how->id, done, NULL);

	oas_msg(sys, self, to, pum_help);
	oas_msg(sys, self, to, pum_focus);
	oas_msg(sys, self, to, pum_how);
	oas_msg(sys, self, to, pum_done);
}

static int
care_act(Rid self, const Rid sender, void *msg, void *local, Oas_sys *sys)
{
	Care *care = local;
	/* Pum_val *val = msg; */

	/* if (!val) */
	/* 	return 1; */

	/* /\* if (!rid_cmp(care->focus, none)) { *\/ */
	/* /\* 	rid_set(care->focus, val->indep); *\/ */
	/* /\* 	oas_msg(sys, val->sender, val); *\/ */
	/* /\* } *\/ */

	/* return 0; */
	Pum_val *val = msg;

	if (val) {
		/* rid_set(val->id, NULL); */
		/* oas_msg(sys, self, sender, val); */
		/* return 0; */
		global_recycle_pum(sys, msg);
		care_ask_help(care, self, sender, sys);
		return 0;
	}

	return 1;

}

static void
care_die(Rid self, Oas_mail *mail, void *local, Oas_sys *sys)
{
	Care *care = local;

	free(care);
}

int
care_add(Oas_sys *sys, const Rid id, const Rid focus)
{
	Care *care = palloc(care);
	Rid_fn85 str;

	if (!care) {
		fprintf(stderr, "Failed to alloc care.\n");
		return -1;
	}

	rid_set(care->focus, focus);

	if (oas_add(sys, id, NULL, care, NULL, care_act, care_die)) {
		fprintf(stderr, "Failed to add care actor.\n");
		free(care);
		return -1;
	}

	rid_fn85(str, id);
	printf("Care id %s\n", str);
	return 0;
}
